from typing import List, Dict
from datetime import datetime

import numpy as np

from vnsumscope.trader.utility import BarGenerator
from vnsumscope.trader.object import TickData, BarData

from vnsumscope.app.portfolio_strategy import (
    StrategyTemplate,
    StrategyEngine
)


class PortFolioStrategy(StrategyTemplate):
    """"""

    parameters = []
    variables = []

    def __init__(
            self,
            strategy_engine: StrategyEngine,
            strategy_name: str,
            vt_symbols: List[str],
            setting: dict
    ):
        """"""
        super().__init__(strategy_engine, strategy_name, vt_symbols, setting)

        # 每个合约的K线合成器字典，用于实盘中将TICK合成为1分钟K线
        self.bgs: Dict[str, BarGenerator] = {}

        # 每个合约的目标仓位字典
        self.targets: Dict[str, int] = {}

        # 最新收到的TICK时间戳，用于控制K线合成
        self.last_tick_time: datetime = None

        # 已缓存记录的K线价差数据
        self.spread_count: int = 0

        # 用numpy.array来缓存价差数据，方便向量化计算
        self.spread_data: np.array = np.zeros(100)

        # 获取现券和期货代码
        self.bond_symbol, self.futures_symbol = vt_symbols

        # 初始化K线合成器，这里不需要回调函数（传空lambda）
        for vt_symbol in self.vt_symbols:
            self.targets[vt_symbol] = 0
            self.bgs[vt_symbol] = BarGenerator(lambda bar: None)

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        pass

    def on_bars(self, bars: Dict[str, BarData]):
        """"""
        pass


if __name__ == '__main__':
    from datetime import datetime
    from importlib import reload

    import vnsumscope.app.portfolio_strategy

    reload(vnsumscope.app.portfolio_strategy)

    from vnsumscope.app.portfolio_strategy import BacktestingEngine
    from vnsumscope.trader.constant import Interval

    import vnsumscope.app.portfolio_strategy.strategies.pair_trading_strategy as stg

    reload(stg)

    engine = BacktestingEngine()
    engine.set_parameters(
        vt_symbols=["190210.CFETS","190203.CFETS"],
        interval="1m",
        start=datetime(2020, 1, 1),
        end=datetime(2020, 10, 30),
        rates={
            "190210.CFETS": 0.3 / 10000,
            "190203.CFETS": 0.3 / 10000
        },
        slippages={
            "190210.CFETS": 0,
            "190203.CFETS": 0
        },
        sizes={
            "190210.CFETS": 10,
            "190203.CFETS": 10
        },
        priceticks={
            "190210.CFETS": 10,
            "190203.CFETS": 10
        },
        capital=1_000_000,
    )

    setting = {
        "price_add": 0.01,
        "boll_window": 20,
        "boll_dev": 1,
        "fixed_size": 1,
        "bond_ratio": 1,
        "futures_ratio": 10,
    }
    engine.add_strategy(PortFolioStrategy, setting)

    engine.load_data()
    engine.run_backtesting()
    df = engine.calculate_result()
    engine.calculate_statistics()
    engine.show_chart()
